
export default class VoiceCorrect {
	
	correctPinyin;
	userPinyin;
	map = {};
	
	/**
	 * @param {Object} correctPinyin ['n', 'i', 3]
	 * @param {Object} userPinyin ['n', 'ing', 3]
	 */
	constructor(correctPinyin, userPinyin) {
		this.correctPinyin = correctPinyin
		this.userPinyin = userPinyin
		this.finals = ["iang","uang","iong","uai","van","ian","iao","ia","ua","uo","ang","eng","ing","ong","an","en","in","un","vn","ve","ai","ei","ui","ao","ou","iu","ie","er","a","o","e","v","i","u"]
		for(let i=0;i<34;++i) {
			this.map[this.finals[i]] = i
		}
	}
	
	// 音调
	toneAnalyse() {
		const correctTone = this.correctPinyin[this.correctPinyin.length-1]
		const userTone = this.userPinyin[this.userPinyin.length-1]
		return correctTone === userTone ? 1 : 0
	}
	// 韵母
	finalsAnalyse() {
		const w = 0.4
			, x = 0.3
			, y = 0.2
			, z = 0.1;
			
		const squre1 = this.squreInit(34)
			, squre2 = this.squreInit(34)
			, squre3 = this.squreInit(34);
			
		for(var j=0;j<34;++j) {
			squre1[j][j] = 1
			squre2[j][j] = 1
			squre3[j][j] = 1
		}
		this.generateComposition(squre1, ['a', 'o', 'e', 'er', 'ai', 'ei', 'ao', 'ou', 'an', 'en', 'ang', 'eng', 'ong'])
		this.generateComposition(squre1, ['i', 'ie', 'iu', 'in', 'ing'])
		this.generateComposition(squre1, ['u', 'ui', 'un'])
		this.generateComposition(squre1, ['v', 've', 'vn'])
		
		this.generateComposition(squre2, ['a', 'o', 'e', 'i', 'u', 'v', 'er'])
		this.generateComposition(squre2, ['ai', 'ei', 'ie', 've', 'ao', 'ou', 'iu', 'ui'])
		this.generateComposition(squre2, ['an', 'en', 'in', 'un', 'vn', 'ang', 'eng', 'ong', 'ing'])
		
		this.generateComposition(squre3, ['i', 'u', 'v'])
		this.generateComposition(squre3, ['ei', 'ie', 've'])
		this.generateComposition(squre3, ['ou', 'iu', 'ui'])
		this.generateComposition(squre3, ['an', 'en', 'in', 'un', 'vn'])
		this.generateComposition(squre3, ['ang', 'eng', 'ong', 'ing'])
		
		
		let ya = ""
		  , yb = ""
		  , start1 = 1
		  , start2 = 1
		if(this.correctPinyin[1] === 'h') {
			start1 = 2
		}
		if(this.userPinyin[1] === 'h') {
			start2 = 2
		}
		let flag1 = false
		  , flag2 = false
		
		for(let i=0;i<34;++i) {
			const _final = this.finals[i]
			const len = this.correctPinyin.length
			const match = this.correctPinyin.slice(start1, Math.min(len-start1, _final.length)+start1).join('')
			if(_final === match) {
				ya = _final
				if(i <= 9) {
					flag1 = true
				}
				break
			}
		}
		
		for(let i=0;i<34;++i) {
			const _final = this.finals[i]
			const len = this.userPinyin.length
			const match = this.userPinyin.slice(start2, Math.min(len-start2, _final.length)+start2).join('')
			if(_final === match) {
				yb = _final
				if(i <= 9) {
					flag2 = true
				}
				break
			}
		}
		
		if(flag1 && flag2) {
			const yac1 = ya[0]
				, yac2 = ya.slice(1)
				, ybc1 = yb[0]
				, ybc2 = yb.slice(1)
			let m1 = 0
			  , m2 = 0
			if(!yac1 || !ybc1) {
				
			} else if (yac1 === ybc1) {
				m1 = 1
			} else {
				const _val_1 = squre1[this.map[yac1]][this.map[ybc1]]
				const _val_2 = squre2[this.map[yac1]][this.map[ybc1]]
				const _val_3 = squre3[this.map[yac1]][this.map[ybc1]]
				m1 = this.getScoreByVal(_val_1, _val_2, _val_3)
			}
			if(!yac2 || !ybc2) {
				
			} else if (yac2 === ybc2) {
				m2 = 1
			} else {
				const _val_1 = squre1[this.map[yac2]][this.map[ybc2]]
				const _val_2 = squre2[this.map[yac2]][this.map[ybc2]]
				const _val_3 = squre3[this.map[yac2]][this.map[ybc2]]
				m2 = this.getScoreByVal(_val_1, _val_2, _val_3)
			}
			return (m1+m2)/2
		}
		if(!flag1 && !flag2) {
			if(!ya || !yb) {
				return 0
			}
			if((ya ===  yb))
				return 1
			const _val_1 = squre1[this.map[ya]][this.map[yb]]
			const _val_2 = squre2[this.map[ya]][this.map[yb]]
			const _val_3 = squre3[this.map[ya]][this.map[yb]]
			return this.getScoreByVal(_val_1, _val_2, _val_3)
		}
		if(!flag1) {
			yb = yb.slice(1)
			if(!ya || !yb) {
				return 0
			}
			if((ya === yb)) {
				return 0.5
			}
			const _val_1 = squre1[this.map[ya]][this.map[yb]]
			const _val_2 = squre2[this.map[ya]][this.map[yb]]
			const _val_3 = squre3[this.map[ya]][this.map[yb]]
			return this.getScoreByVal(_val_1, _val_2, _val_3) / 2
		}
		ya = ya.slice(1)
		if(!ya || !yb) {
			return 0
		}
		if((ya === yb)) {
			return 0.5
		}
		const _val_1 = squre1[this.map[ya]][this.map[yb]]
		const _val_2 = squre2[this.map[ya]][this.map[yb]]
		const _val_3 = squre3[this.map[ya]][this.map[yb]]
		return this.getScoreByVal(_val_1, _val_2, _val_3) / 2
		
		
		
	}
	// 声母
	consonantAnalyse() {
		let af = 0.5
		  , bt = 0.5
		const consonants = ["zh","ch","sh","b","p","m","f","d","t","n","l","g","k","h","j","q","x","z","c","s","y","w","r"]
		const map = {}
		for(let i=0;i<23;++i) {
			map[consonants[i]] = i
		}
		const squre1 = this.squreInit(23)
			, squre2 = this.squreInit(23)
		this.generateComposition(squre1, ['b', 'p', 'm', 'w'], map)
		this.generateComposition(squre1, ['d', 't', 'n', 'l'], map)
		this.generateComposition(squre1, ['g', 'k', 'h'], map)
		this.generateComposition(squre1, ['j', 'q', 'x'], map)
		this.generateComposition(squre1, ['zh', 'ch', 'sh', 'r'], map)
		this.generateComposition(squre1, ['z', 'c', 's', 'y'], map)
		
		this.generateComposition(squre2, ['b', 'd', 'g'], map)
		this.generateComposition(squre2, ['p', 't', 'k'], map)
		this.generateComposition(squre2, ['j', 'zh', 'z'], map)
		this.generateComposition(squre2, ['ch', 'q', 'c'], map)
		this.generateComposition(squre2, ['f', 'h', 'x', 'sh', 's'], map)
		this.generateComposition(squre2, ['m', 'n'], map)
		this.generateComposition(squre2, ['w', 'y'], map)
		
		let flag1 = false
		  , flag2 = false
		let sa = null
		  , sb = null
		
		for(let i=0;i<23;++i) {
			if(consonants[i] === this.correctPinyin.slice(0, consonants[i].length).join('')) {
				flag1 = true
				sa = consonants[i]
				break
			}
		}
		for(let i=0;i<23;++i) {
			if(consonants[i] === this.userPinyin.slice(0, consonants[i].length).join('')) {
				flag2 = true
				sb = consonants[i]
				break
			}
		}
		if(flag1 !== flag2)
			return 0
		const _val_1 = squre1[map[sa]][map[sb]]
		const _val_2 = squre2[map[sa]][map[sb]]
		if((!flag1 && !flag2) || (_val_1 && _val_2))
			return 1
		if(_val_2 ) return af
		if(_val_1) return bt
		return 1
	}
	getScoreByVal(_val_1, _val_2, _val_3) {
		if(_val_1 && _val_3) {
			return w
		}
		if (_val_1 && _val_2) {
			return x
		}
		if (_val_1 && !_val_2) {
			return y
		}
		if (!_val_1 && _val_3) {
			return z
		}
		return 0
		
	}
	squreInit(len) {
		const squre = []
		const elem = []
		for(let i=0;i<len;++i) {
			elem.push(0)
		}
		for(let i=0;i<len;++i) {
			const elem_copy = JSON.parse(JSON.stringify(elem))
			squre.push(elem_copy)
		}
		return squre
	}
	generateComposition(squre, finals, map) {
		map = map ? map : this.map
		const len = finals.length
		for(let i=0;i<len;++i) {
			for(let j=0;j<len;++j) {
				if( i === j ) continue 
				const row = map[finals[i]]
				const col = map[finals[j]]
				squre[row][col] = 1
			}
		}
	}
}